這是個人很久以前在閒暇之餘寫的一個專案,技術多為爬蟲觀念,後來整合 GitHub Action,讓他人 fork 之後就能直接享用。此篇文章會教如何自動登入 iThelp,理解觀念與實作後再帶你直接 fork 此專案並做一些設定,讓 GitHub Action 幫你天天賺取登入點數。
若想直接使用此專案,請直接跳到下方的「不想寫程式?早 fork 早享用」章節閱讀使用說明。
許多論壇都擁有活動點數制度,「iT邦幫忙」也不意外的擁有這項功能,其中有一項是每天登入可以加 2 點活動點數,但不知道是 Bug 還是故意的,竟然需要先登出再登入,有了登入的動作才會計算當天登入的活動點數,很不符合常理。
因此利用爬蟲技能寫了一個專案,每天到指定時間會自動完成登入動作,讓我就算沒有登入這個動作,也可以得到活動點數,雖說這個點數量不多,但就是想要抵抗這個 Bug。
詳細登入問題也有人提請官方修正,可參考 關於IT邦登入時點數的問題。
在動手爬蟲之前,必須先觀察在登入計算活動點數時,會經過哪些步驟與所需資訊,觀察時請記得使用開發人員工具 (F12) 來查看資訊流動。
第一步至 iThome會員登入頁面 任意輸入一組帳號,按下登入按鈕然後查看封包,會看到有三個欄位分別為 _token
、account
還有 password
account
與 password
我們理解,但是 _token
的值從何而來呢?到開發人員工具的 Elements
頁籤搜尋 _token
,就可以找到它所在位置,原來是在登入表單內的一個隱藏欄位 (hidden input)!
知道登入需要甚麼資訊,且資訊在哪裡可以取得,就可以開始規劃要如何利用爬蟲來做登入功能。
_token
欄位的值。_token
、account
與 password
一起 POST
到 https://member.ithome.com.tw/login
需要注意的是,這些過程中的 Cookie
需要被維護,也就是每個 Request 都必須是同一個 Session
,否則 _token
值無效。強大的 requests
套件已經幫我們準備好 Session
物件來處理這些事情,讓我們不用手動轉移 Cookie
到不同的 request 之中。
# 從 sAccount.json 檔案讀取帳密資料
s_account = json.load(open("./sAccount.json", "r", encoding="utf-8"))
# 更改 User-Agent 標頭以免被阻擋
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36"}
# 製作 Payload,有三個欄位分別為 _token、account 與 password
loginPayload = {'account': s_account['account'], 'password': s_account['password'], '_token':''}
# 建立一個 Session 物件幫我們維護 Coookie 的運行
sess = requests.Session()
# 將 User-Agent 標頭修改為我們所給的值
sess.headers.update(headers)
# 先取得 _token 值
url = "https://member.ithome.com.tw/login"
response = sess.get(url)
bsObj = bs(response.text, "html.parser")
loginToken = bsObj.find('input', {'name':'_token'}).attrs['value']
# 把 _token 值存到我們之前建立的 Payload 內
loginPayload['_token'] = loginToken
# 對登入頁面 POST 一次,就可以順利登入囉
url = "https://member.ithome.com.tw/login"
response = sess.post(url, data=loginPayload)
sAccount.json
內容如下,只需填入對應的帳號密碼
{
"account": "",
"password": ""
}
到這裡,登入功能已經完成了。但假如真的去運行這個程式碼,你會發現雖然成功登入,可是並沒有取得想要的到的每日登入活動點數,這個是因為登入與取得點數的功能是分開運行的。
再讓我們觀察一下取得活動點數的關鍵在哪裡。先進入 iT邦幫忙,再點擊登入按鈕,這次需要輸入正確的帳號密碼,並且觀察開發人員工具中的封包,將會看到其實在成功登入後,從 會員中心 跳轉回 iT邦幫忙 之前還有其他封包被傳送,可以猜測這些封包就是用來激活每日登入的條件
也就是說當我們的爬蟲成功登入後,需要發出 GET https://member.ithome.com.tw/oauth/authorize?client_id=ithelp&redirect_uri=https://ithelp.ithome.com.tw/users/callback&response_type=code
請求,來取得這天的每日登入活動點數。
這是最簡單的部分,只需要在登入之後加上下面兩行程式,就可以達到效果了
url = "https://member.ithome.com.tw/oauth/authorize?client_id=ithelp&redirect_uri=https://ithelp.ithome.com.tw/users/callback&response_type=code"
response = sess.get(url)
到這裡,概念與實作講解完畢,當然除登入並取得點數外,還可以加一些功能例如確認是否真的登入或者是是否有錯誤發生的判斷。
可以到我的 GitHub 上參考 完整原始碼。
然而這個 Bug 在 2021/05/12
時小財神宣布已經根除 (關於IT邦登入時點數的問題),真是皆大歡喜。得知這個訊息的第一個想法是這個專案好像沒有用了,但其實我們還是一樣可以繼續排程,若是哪天較忙忘記瀏覽論壇,可讓爬蟲代替我們每天取得點數。
此專案能夠透過 GitHub Action 自動排程,因此讀者只需要直接 Fork 此專案,並添加對應的 secrets
環境變數,即可使用此專案的自動登入功能!接下來將補充說明如何使用 Fork 並透過 Action 排程與運行此專案。
在專案頁面中點擊 Fork
,看到 forked from weirenxue/ithelp-login-script
即為 Fork 成功!
將 iThelp 帳號密碼加入 secrets
環境變數,變數名稱需要完全相同 (注:任何存在 secrets
環境變數中的數值都是加密過的,因此可以放心輸入)
因為此專案來源為 Fork,GitHub 預設關閉透過 Fork 而來的 Repo 其 Action 功能與 Workflow,因此需要手動啟用
最後只需要手動執行 Workflow 即可測試是否能正常地自動登入 iThelp 論壇
Workflow 可以透過 GitHub Action schedule 來描述何時該執行,即排程的做法。當指定的時間到來,則可以直接在 GitHub 上運行,不用額外開機器去執行,非常方便!
目前專案的排程設定可以在 .github/workflows/main.yml
中找到,預設為每日的 12 點執行此 Workflow。這裡指的是 UTC+0 的時間,所以 GitHub Action 12 點 (UTC+0) 對應到台灣時間為晚上 8 點 (UTC+8)
schedule:
- cron: "0 12 * * *"
若讀者想要自定義排程時間,這裡提供相對應的時間說明供讀者參考,讀者可以在 Fork 後的專案自行更改!
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of the month (1 - 31)
│ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
│ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
│ │ │ │ │
│ │ │ │ │
│ │ │ │ │
* * * * *